package com.sansan.qiangji.realize.system;

import com.sansan.qiangji.VO.system.user.UserListResultVO;
import com.sansan.qiangji.VO.system.user.UserVO;
import com.sansan.qiangji.constant.RedisConstant;
import com.sansan.qiangji.entity.system.Menu;
import com.sansan.qiangji.entity.system.Power;
import com.sansan.qiangji.entity.system.User;
import com.sansan.qiangji.enums.ResultEnum;
import com.sansan.qiangji.exception.ServiceException;
import com.sansan.qiangji.form.system.user.UserListForm;
import com.sansan.qiangji.form.system.user.UserMenuPowerEditForm;
import com.sansan.qiangji.form.system.user.UserRegisterForm;
import com.sansan.qiangji.service.impl.system.MenuServiceImpl;
import com.sansan.qiangji.service.impl.system.PowerServiceImpl;
import com.sansan.qiangji.service.inter.system.UserService;
import com.sansan.qiangji.utils.DateUtil;
import com.sansan.qiangji.utils.JWTUtil;
import com.sansan.qiangji.utils.MD5Util;
import com.sansan.qiangji.utils.pageUtils.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserReal {
    private UserService userService;
    private StringRedisTemplate stringRedisTemplate;
    private MenuServiceImpl menuService;
    private PowerServiceImpl powerService;

    @Resource
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Resource
    private void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Resource
    public void setMenuService(MenuServiceImpl menuService){
        this.menuService = menuService;
    }

    @Resource
    public void setPowerService(PowerServiceImpl powerService){
        this.powerService = powerService;
    }

    public UserListResultVO userList(UserListForm userListForm) {
        PageResult<User> pageResultUser = userService.userList(userListForm);
        UserListResultVO userListResultVO = new UserListResultVO();
        BeanUtils.copyProperties(pageResultUser, userListResultVO);
        List<UserVO> userVOS = new ArrayList<>();
        for (User user : pageResultUser.getContent()) {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            userVOS.add(userVO);
        }
        userListResultVO.setUserVOS(userVOS);
        return userListResultVO;
    }

    @Transactional
    public void userRegister(UserRegisterForm userRegisterForm) {
        User user = userService.findByUserName(userRegisterForm.getUserName());
        if (user != null) {
            log.error("【用户登录】用户已存在，userRegisterForm={}", userRegisterForm.toString());
            throw new ServiceException(ResultEnum.USER_IS_EXIST);
        }
        user = new User();
        BeanUtils.copyProperties(userRegisterForm, user);
        user.setUserPasswordMd5(MD5Util.MD5(user.getUserPassword()));
        user.setUserStatus(true);
        int rows = userService.addUser(user);
        if (rows == 0) {
            log.error("【用户注册】注册失败，user={}", user.toString());
            throw new ServiceException(ResultEnum.USER_REGISTER);
        }
    }

    public UserVO userLogin(String userName, String userPassword) {
        User user = userService.findByUserName(userName);
        if (user == null) {
            log.error("【用户登录】用户不存在，userName={}", userName);
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        if (!user.getUserStatus()) {
            log.error("【用户登录】用户已被冻结，userName={}", userName);
            throw new ServiceException(ResultEnum.USER_FREEZE);
        }
        String userPasswordMd5 = MD5Util.MD5(userPassword);
        if (!user.getUserPasswordMd5().equals(userPasswordMd5)) {
            log.error("【用户登录】用户密码错误，userName={}, userPassword={}", userName, userPassword);
            throw new ServiceException(ResultEnum.USER_PASSWORD_ERROR);
        }
        UserVO userVO = new UserVO();
        String tokenKey = UUID.randomUUID().toString();
        Integer expire = RedisConstant.EXPIRE;
        String nowTime = DateUtil.nowString("yyyy-MM-dd HH:mm:ss");
        String tokenValue = JWTUtil.getJsonWebToken(user.getUserName(), nowTime, "windowLogin");
        stringRedisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, tokenKey), tokenValue, expire, TimeUnit.SECONDS);
        BeanUtils.copyProperties(user, userVO);
        userVO.setToken(tokenKey);
        return userVO;
    }

    @Transactional
    public void deleteUser(Integer userId) {
        User user = userService.findByUserId(userId);
        if (user == null) {
            log.error("【用户删除】用户不存在，userId={}", userId);
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        int rows = userService.deleteById(userId);
        if (rows == 0) {
            log.error("【用户删除】用户删除失败，user={}", user.toString());
            throw new ServiceException(ResultEnum.USER_DELETE_ERROR);
        }
    }

    @Transactional
    public void changeUserStatus(Integer userId) {
        User user = userService.findByUserId(userId);
        if (user == null) {
            log.error("【更改用户状态】用户不存在，userId={}", userId);
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        user.setUserStatus(!user.getUserStatus());
        int rows = userService.updateUser(user);
        if (rows == 0) {
            log.error("【更改用户状态】更改用户状态失败，userId={}", userId);
            throw new ServiceException(ResultEnum.CHANGE_USER_STATUS_ERROR);
        }
    }

    @Transactional
    public void editUserRole(Integer userId, String roleName){
        User user = userService.findByUserId(userId);
        if (user == null) {
            log.error("【编辑用户角色】用户不存在，userId={}", userId);
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        user.setRoleName(roleName);
        int rows = userService.updateUser(user);
        if (rows == 0) {
            log.error("【编辑用户角色】编辑用户角色失败，userId={}", userId);
            throw new ServiceException(ResultEnum.CHANGE_USER_STATUS_ERROR);
        }
    }

    @Transactional
    public void userMenuPowerEdit(UserMenuPowerEditForm userMenuPowerEditForm) {
        User user = userService.findByUserId(userMenuPowerEditForm.getUserId());
        if (user == null) {
            log.error("【用户菜单权限编辑】用户不存在");
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        List<Menu> menus = menuService.findAllMenu();
        StringBuilder roleMenus = new StringBuilder();
        for (String menuRoot : userMenuPowerEditForm.getUserMenuPowers()){
            if (menus.stream().anyMatch(e -> e.getMenuRoot().equals(menuRoot))) {
                if (roleMenus.toString().equals("")){
                    roleMenus = new StringBuilder(menuRoot);
                }else
                {
                    roleMenus.append("||").append(menuRoot);
                }
            }
        }
        user.setUserMenus(roleMenus.toString());
        int rows = userService.updateUser(user);
        if (rows == 0){
            log.error("【角色菜单权限编辑】角色菜单权限编辑失败，roleMenuPowerEditForm={}", userMenuPowerEditForm.toString());
            throw new ServiceException(ResultEnum.ROLE_MENU_POWER_EDIT_ERROR);
        }
    }

    @Transactional
    public void userPowerEdit(Integer userId, String powerName) {
        User user = userService.findByUserId(userId);
        if (user == null) {
            log.error("【用户权限编辑】用户不存在");
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        List<Power> powers = powerService.findByPowerName(powerName);
        if (powers.size() == 0) {
            log.error("【用户权限编辑】权限不存在");
            throw new ServiceException(ResultEnum.POWER_NOT_EXIST);
        }
        List<String> userPowers = new ArrayList<>(Arrays.asList(user.getUserPowers().split("\\|\\|")));
        if (!userPowers.contains(powerName)){
            userPowers.add(powerName);
        }else {
            userPowers.remove(powerName);
        }
        user.setUserPowers(StringUtils.join(userPowers, "||"));
        int rows = userService.updateUser(user);
        if (rows == 0){
            log.error("【用户权限编辑】用户权限编辑失败");
            throw new ServiceException(ResultEnum.USER_POWER_EDIT_ERROR);
        }
    }
}
